#ifndef cathlibcpp_istream_H
#define cathlibcpp_istream_H

// File:       istream.h
// Author:     (c) Miles Sabin, 1997
// Purpose:    approximation to ANSI C++ istream header


#ifndef cathlibcpp_bool_H
#include "bool.h"
#endif

#ifndef cathlibcpp_config_H
#include "config.h"
#endif

#ifndef cathlibcpp_ios_H
#include "ios.h"
#endif

#ifndef cathlibcpp_newcasts_H
#include "newcasts.h"
#endif

#ifndef cathlibcpp_string_H
#include "string.h"               // for char_traits_char
#endif


class basic_istream_char;
typedef basic_istream_char istream;

class basic_istream_char : virtual public basic_ios_char
{
  friend class IStreamCommand;
  friend class basic_istream_char_sentry;

  public:

    // types
    typedef char_traits_char traits;

    // constructors
    basic_istream_char(basic_streambuf_char* sb);
    virtual ~basic_istream_char();

    // formatted input
    basic_istream_char& operator>>(basic_istream_char& (*pf)(basic_istream_char&));
    basic_istream_char& operator>>(basic_ios_char& (*pf)(basic_ios_char&));
    basic_istream_char& operator>>(ios_base& (*pf)(ios_base&));

#ifdef BUILTIN_BOOL
    basic_istream_char& operator>>(bool& n);
#endif
    basic_istream_char& operator>>(short& n);
    basic_istream_char& operator>>(unsigned short& n);
    basic_istream_char& operator>>(int& n);
    basic_istream_char& operator>>(unsigned int& n);
    basic_istream_char& operator>>(long& n);
    basic_istream_char& operator>>(unsigned long& n);
    basic_istream_char& operator>>(float& f);
    basic_istream_char& operator>>(double& f);

    basic_istream_char& operator>>(void*& p);

    basic_istream_char& operator>>(basic_streambuf_char* sb);

    // unformatted input
    streamsize gcount() const;
    int get();
    basic_istream_char& get(char& c);

    basic_istream_char& get(char* s, streamsize n)
      { return get(s, n, '\n'); }
    basic_istream_char& get(char* s, streamsize n, char delim);

    basic_istream_char& get(basic_streambuf_char* sb)
      { return get(sb, '\n'); }
    basic_istream_char& get(basic_streambuf_char* sb, char delim);

    basic_istream_char& getline(char* s, streamsize n)
      { return getline(s, n, '\n'); }
    basic_istream_char& getline(char* s, streamsize n, char delim);

    basic_istream_char& ignore(streamsize n = 1, int delim = traits::eof());

    int peek();

    basic_istream_char& read(char* s, streamsize n);
    streamsize readsome(char* s, streamsize n);

    basic_istream_char& putback(char c);
    basic_istream_char& unget();
    int sync();

    int tellg();
    basic_istream_char& seekg(int pos);
    basic_istream_char& seekg(int off, seekdir dir);

  private:

    // not implemented
    basic_istream_char(basic_istream_char const&);
    basic_istream_char& operator=(basic_istream_char const&);

    int gcount_;
};

basic_istream_char& operator>>(basic_istream_char& is, char& c);
basic_istream_char& operator>>(basic_istream_char& is, unsigned char& c);

basic_istream_char& operator>>(basic_istream_char& is, char* c);
basic_istream_char& operator>>(basic_istream_char& is, unsigned char* c);

basic_istream_char& ws(basic_istream_char& is);


class basic_istream_char_sentry
{
  public:

    basic_istream_char_sentry(basic_istream_char& is, bool noskipws = false);
    ~basic_istream_char_sentry();

    operator bool()
      { return ok_; }

  private:

    basic_istream_char& is_;
    bool ok_;
};


// implementation of basic_istream_char

inline basic_istream_char& basic_istream_char::operator>>(basic_istream_char& (*pf)(basic_istream_char&))
  { return pf(*this); }

inline basic_istream_char& basic_istream_char::operator>>(basic_ios_char& (*pf)(basic_ios_char&))
  {
    pf(*this);
    return *this;
  }

inline basic_istream_char& basic_istream_char::operator>>(ios_base& (*pf)(ios_base&))
  {
    pf(*this);
    return *this;
  }

inline streamsize basic_istream_char::gcount() const
  { return gcount_; }


// implementation of basic_istream_char free fns

inline basic_istream_char& operator>>(basic_istream_char& is, unsigned char& c)
{
  return operator>>(is, reinterpret_cast(char&, c));
}

inline basic_istream_char& operator>>(basic_istream_char& is, unsigned char* s)
{
  return operator>>(is, reinterpret_cast(char*, s));
}

#endif
